﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.FxCop.Sdk;
using System.Xml;
using System.Reflection;
using System.IO;

namespace SinacorRules
{
    public sealed class Rule_ControlPrefix : BaseAddIn.Rules.BaseRuleFXCop
    {
        #region Cosntantes

        const string NAMESPACE_CONTROLS = "Sinacor.Infra.UI.Controls.SmartClient";

        #endregion

        #region Fields

        private XmlDocument _document;
        private XmlNode _node;

        private List<ControlPrefix> _controlList;

        #endregion

        #region Constructor

        public Rule_ControlPrefix() :
            base("ControlPrefix", "SinacorRules.SinacorRules", typeof(Rule_ControlPrefix).Assembly)
        {
            Assembly assembly = Assembly.GetExecutingAssembly();
            Stream stream = assembly.GetManifestResourceStream("SinacorRules.ControlPrefix.xml");

            this._document = new XmlDocument();
            this._document.Load(stream);
            this._node = _document["Controls"];

            this._controlList = new List<ControlPrefix>();

            foreach (XmlNode node in this._node.ChildNodes)
            {
                this._controlList.Add(new ControlPrefix(node.Attributes["Name"].Value, node.Attributes["Prefix"].Value));
            }

            this._node = null;
            this._document = null;

        }

        #endregion

        #region Public Override Methods

        public sealed override ProblemCollection Check(Member member)
        {
             if (member.NodeType == NodeType.Field)
            {
                ClassNode classNode = (member as Field).Type as ClassNode;

                if (classNode != null && classNode.Namespace.Name.Equals(NAMESPACE_CONTROLS))
                {
                    this.CheckControlName(member.Name.Name, classNode, member.DeclaringType);
                }
            }
            
            return this.Problems;
        }

        #endregion

        #region Private Methods

        private void CheckControlName(String controlNameProperty, ClassNode classNode, TypeNode nodeDeclaringType)
        {
            var result = (from control in this._controlList
                          where control.ControlName == classNode.Name.Name
                          select control).SingleOrDefault();

            if (result != null)
            {
                ControlPrefix _controlPrefix = result as ControlPrefix;
                
                if (!controlNameProperty.StartsWith(_controlPrefix.ControlPrefixName))
                {
                    AddError(classNode,
                        "ControlPrefixResolution",
                        classNode.Name.Name,
                        _controlPrefix.ControlPrefixName,
                        nodeDeclaringType.Name.Name,
                        nodeDeclaringType.Namespace.Name);
                }
            }
        }

        #endregion
    }
}
